package com.intellif.mozping.singleton;

/**
 * @author by mozping
 * @Classname SingletonDcl
 * @Description DCL双重校验的单例模式
 * @Date 2019/5/14 13:39
 */
public class SingletonDcl {

    /**
     * 增加volatile关键字，保证内存的可见性和禁止指令重排，后者可以保证线程初始化singleton的时候执行顺序不会被重排
     * 前者可以保证一个线程初始化了singleton之后，对另一个线程立刻可见
     */
    private static volatile SingletonDcl singleton;

    private SingletonDcl() {
    }

    public static SingletonDcl getInstance() {
        if (singleton == null) {
            synchronized (SingletonDcl.class) {
                if (singleton == null) {
                    /*
                      这里不是原子操作，这里包含3步,这里的指令重排可能导致3步骤还未执行完，另一个线程就在外面判定singleton不是null，
                      导致另一个线程获取到的singleton是不完整的
                      1.分配一块内存空间
                      2.在这块内存上初始化一个DoubleCheckLock的实例
                      3.将声明的引用instance指向这块内存
                     */
                    singleton = new SingletonDcl();
                }
            }
        }
        return singleton;
    }

}